local tazhen = fk.CreateSkill {

  name = "joy__tazhen",

  tags = { Skill.Compulsory, },

}



tazhen:addEffect(fk.TurnStart, {
  name = "joy__tazhen",
  anim_type = "offensive",
  frequency = Skill.Compulsory,
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(tazhen.name) and target == player
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local victims, record = {}, {}
    -- prepare tazhen content
    local targets = table.map(room:getOtherPlayers(player, false), Util.IdMapper)
    if #targets > 0 then
      local list = table.random(targets, 3)
      local blank_num = 3 - #list
      if blank_num > 0 then
        blank_num = math.random(blank_num + 1) - 1
        for i = 1, blank_num do
          table.insert(list, "blank")
        end
      end
      for i = 1, math.random(2, 5) do
        table.insert(list, "slash")
      end
      for i = #list, 8 do
        table.insert(list, table.random({"analeptic", "horse"}))
      end
      table.shuffle(list)
      local result = room:askForCustomDialog(
        player, tazhen.name,
        "packages/joy/qml/TazhenBox.qml",
        { list, math.max(0, player.hp) + 1 }
      )
      -- check tazhen rewards
      if result ~= "" then
        result = result
        local choices = table.map(result, function(i) return i + 1 end)
        if table.contains(choices, 5) then
          table.insert(record, "main")
        end
        for i, v in ipairs(choices) do
          local next, nnext = choices[i+1], choices[i+2]
          if nnext == nil then break end
          if math.abs(v - next) == 1 and (v - next) == (next - nnext) then
            table.insert(record, "line")
            break
          end
        end
        for i, v in ipairs(choices) do
          local next, nnext = choices[i+1], choices[i+2]
          if nnext == nil then break end
          if math.abs(v - next) == 3 and (v - next) == (next - nnext) then
            table.insert(record, "row")
            break
          end
        end
        local atk, buff = 0, 0
        for _, index in ipairs(choices) do
          local dat = list[index]
          if dat == "slash" then
            atk = atk + 1
          elseif dat == "analeptic" then
            buff = buff + 2
          elseif type(dat) == "number" then
            local hp = room:getPlayerById(dat).hp
            if buff + atk >= hp then
              table.insert(victims, dat)
            end
            buff = 0
          end
        end
      end
    end
    room:sendLog{ type = "#JoyTazhenResult", from = player.id, arg = #victims > 0 and "success" or "fail", toast = true }
    if #victims == 0 then return false end
    local slash = room:getCardsFromPileByRule("slash")
    if #slash > 0 then
      room:moveCards({
        ids = slash,
        to = player.id,
        toArea = Player.Hand,
        moveReason = fk.ReasonJustMove,
        proposer = player.id,
        skillName = tazhen.name,
      })
    end
    if player.dead then return end
    if not player:hasSkill("wushuang", true) then
      room:setPlayerMark(player,tazhen.name,1)
      room:handleAddLoseSkills(player, "wushuang")
      if player.dead then return end
    end
    room:sortPlayersByAction(victims)
    room:doIndicate(player.id, victims)
    victims = table.map(victims, Util.Id2PlayerMapper)
    if not table.contains(record, "line")  then
      for _, p in ipairs(victims) do
        if player.dead then break end
        if not p.dead and not p:isNude() then
          local cards = room:askForCard(p, 1, 1, true, tazhen.name, false, ".", "#joy__tazhen-give:"..player.id)
          room:moveCardTo(cards,Player.Hand,player,fk.ReasonGive,tazhen.name,nil,false,p)
        end
      end
    end
    if not table.contains(record, "row") then
      for _, p in ipairs(victims) do
        if player.dead then break end
        if not p.dead then
          room:useVirtualCard("slash", nil, player, p, tazhen.name, true)
        end
      end
    end
    if not table.contains(record, "main") then
      local mark = player:getTableMark( "joy__tazhen_target")
      for _, p in ipairs(victims) do
        if not p.dead and table.insertIfNeed(mark, p.id) then
          room:addPlayerMark(p, "@@joy__tazhen")
        end
      end
      room:setPlayerMark(player, "joy__tazhen_target", mark)
    end
  end,
})
tazhen:addEffect(fk.TurnStart, {
  refresh_events = {fk.TurnStart, fk.BuryVictim},
  can_refresh = function (self, event, target, player, data)
    return target == player and (player:getMark(tazhen.name) ~= 0 or player:getMark("joy__tazhen_target") ~= 0)
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if player:getMark(tazhen.name) > 0  then
      room:setPlayerMark(player, tazhen.name, 0)
      room:handleAddLoseSkills(player, "-wushuang")
    end
    local mark = player:getMark("joy__tazhen_target")
    if mark ~= 0 then
      room:setPlayerMark(player, "joy__tazhen_target", 0)
      for _, pid in ipairs(mark) do
        local p = room:getPlayerById(pid)
        room:removePlayerMark(p, "@@joy__tazhen")
      end
    end
  end,
})
tazhen:addEffect(fk.BuryVictim, {
  refresh_events = {fk.TurnStart, fk.BuryVictim},
  can_refresh = function (self, event, target, player, data)
    return target == player and (player:getMark(tazhen.name) ~= 0 or player:getMark("joy__tazhen_target") ~= 0)
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if player:getMark(tazhen.name) > 0  then
      room:setPlayerMark(player, tazhen.name, 0)
      room:handleAddLoseSkills(player, "-wushuang")
    end
    local mark = player:getMark("joy__tazhen_target")
    if mark ~= 0 then
      room:setPlayerMark(player, "joy__tazhen_target", 0)
      for _, pid in ipairs(mark) do
        local p = room:getPlayerById(pid)
        room:removePlayerMark(p, "@@joy__tazhen")
      end
    end
  end,
})

tazhen:addEffect("prohibit", {
  name = "#joy__tazhen_prohibit",
  is_prohibited = function(self, from, to, card)
    return from and to and table.contains(to:getTableMark( "joy__tazhen_target") ,from.id) and card and card.trueName == "slash"
  end,
})

return tazhen